home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 11
/
CU Amiga Magazine's Super CD-ROM 11 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-06].iso
/
cucd
/
programming
/
oberonv4
/
source
/
system
/
rx.mod
(
.txt
)
< prev
next >
Wrap
Oberon Text
|
1995-10-30
|
12KB
|
371 lines
Syntax10.Scn.Fnt
Syntax10i.Scn.Fnt
MODULE RX; (* Andreas Margelisch, 1990 *)
IMPORT RXA, Oberon, Texts, Viewers, MenuViewers, TextFrames, Display;
CONST
blank = 32; (* blank *)
tab = 9; (* tab *)
cr = 13; (* carriage return *)
dq = 34; (* double quotes *)
noerror = 0;
strtoolong = -1;
linetoolong = -2;
(* nofline = 32000; *) nofline = 20000;
(* nofrepl = 32000; *) nofrepl = 20000;
w: Texts.Writer;
sbeg, send, errorvar : INTEGER;
sdfa : RXA.DFA;
stext : Texts.Text;
stextpos, slinelen : LONGINT;
sline : ARRAY(nofline+1) OF CHAR;
sreplaced, casesens, replset : BOOLEAN;
replstr : ARRAY(nofrepl+1) OF CHAR;
ch : CHAR;
PROCEDURE Focus():TextFrames.Frame;
VAR f : Display.Frame;
BEGIN
IF Oberon.FocusViewer.state > 1 THEN
f := Oberon.FocusViewer.dsc;
IF ( f # NIL ) & ( f.next # NIL ) & ( f.next IS TextFrames.Frame ) THEN RETURN f.next( TextFrames.Frame ) END;
END;
RETURN NIL
END Focus;
PROCEDURE MyCAP( ch : CHAR ) : CHAR;
BEGIN IF ("a" <= ch ) & ( ch <= "z" ) THEN RETURN CAP( ch ) ELSE RETURN ch END;
END MyCAP;
PROCEDURE GetText( VAR text : Texts.Text; VAR name : ARRAY OF CHAR; VAR s : Texts.Scanner );
f : Display.Frame;
ss : Texts.Scanner;
v : Viewers.Viewer;
BEGIN
Texts.Scan( s );
text := NIL; name[0] := 0X;
IF s.class = Texts.Name THEN
NEW( text ); Texts.Open( text, s.s ); COPY( s.s, name );
ELSIF ( s.class = Texts.Char ) & ( s.c = "*" ) THEN
v := Oberon.MarkedViewer();
f := v.dsc;
IF ( v.state > 1 ) & ( f # NIL ) & ( f.next # NIL ) & ( f.next IS TextFrames.Frame ) THEN
IF ( f IS TextFrames.Frame ) THEN
Texts.OpenScanner( ss, f(TextFrames.Frame ).text, 0 ); Texts.Scan( ss );
IF ss.class = Texts.Name THEN COPY ( ss.s, name) END;
END;
text := f.next( TextFrames.Frame ).text;
END;
END;
END GetText;
PROCEDURE GetOption( VAR reader : Texts.Reader; VAR opti : BOOLEAN );
BEGIN
casesens := TRUE;
opti := FALSE;
Texts.Read( reader, ch );
WHILE ( ORD(ch) = tab ) OR ( ORD(ch) = blank ) OR ( ORD(ch) = cr ) DO Texts.Read( reader, ch ) END;
IF ch = "\" THEN
REPEAT
Texts.Read( reader, ch );
CASE ch OF
"c" : casesens := ~casesens |
"i" : opti := ~opti |
"~" : RETURN;
ELSE
END;
UNTIL ( ORD(ch) = blank ) OR ( ORD(ch) = cr ) OR ( ORD(ch) =tab );
END;
END GetOption;
PROCEDURE GetStr( VAR reader : Texts.Reader; VAR str : ARRAY OF CHAR );
VAR strfull, inquotes, first : BOOLEAN;
strind : INTEGER;
PROCEDURE Append( chr : CHAR );
BEGIN
IF strind < LEN( str ) THEN str[strind] := chr; INC(strind) ELSE strfull := TRUE END;
END Append;
BEGIN
strfull := FALSE; strind := 0; inquotes := FALSE; first := FALSE;
WHILE ( ORD(ch) = tab ) OR ( ORD(ch) = cr ) OR ( ORD(ch) = blank ) DO Texts.Read( reader, ch ) END;
WHILE ( ~reader.eot ) & ( ORD(ch) # cr ) DO
IF ~first & ( ORD(ch) = dq ) THEN inquotes := ~inquotes; first := inquotes; Append( ch );
ELSE
IF inquotes & ~casesens THEN Append( MyCAP( ch ) ) ELSE Append( ch ) END;
first := FALSE;
END;
Texts.Read( reader, ch );
END;
Append( CHR(0) );
IF strfull THEN errorvar := strtoolong END;
END GetStr;
PROCEDURE RXAErrorHandler( error, pos : INTEGER );
BEGIN
CASE error OF
RXA.noposfree : Texts.WriteString( w,"regular expression too long ( position table full )") |
RXA.nostatesfree : Texts.WriteString( w,"regular expression too long ( state table full )") |
RXA.nometaexp : Texts.WriteString( w,"no metasymbol at pos "); Texts.WriteInt( w, pos, 3 );
Texts.WriteString( w," expected ") |
RXA.chrleft : Texts.WriteString( w,"regular expression not correct ( ')', ']' or '}' on a wrong place )") |
RXA.wsubexpr : Texts.WriteString( w,"subexpression, String or shorthands 't' or 'c' at pos "); Texts.WriteInt( w,pos, 3);
Texts.WriteString( w," expected ") |
RXA.subexprrest : Texts.WriteString( w,"marked subexpression at pos "); Texts.WriteInt( w,pos, 3);
Texts.WriteString( w," shouldn't be enclosed by '{ }' ") |
RXA.wshorthand : Texts.WriteString( w,"wrong shorthand identifier at pos "); Texts.WriteInt( w,pos, 3); Texts.WriteLn( w );
Texts.WriteString( w,"permitted are : A, a, b, c, d, h, i, l, o, t, w ") |
RXA.nodfa : Texts.WriteString( w,"replace faild : automata is missing") |
RXA.repllinefull : Texts.WriteString( w,"replace faild : replacestring is full ") |
RXA.notnotexp : Texts.WriteString( w,"metasymbol or more than one literal in qutoes after notoperator") |
RXA.linecopofl : Texts.WriteString( w, "array linecop in RXA.Replace is too small");
ELSE
Texts.Write(w, "'"); Texts.Write(w, CHR(error)); Texts.Write(w, "'"); Texts.WriteString( w," at pos ");
Texts.WriteInt( w,pos, 3); Texts.WriteString( w," expected ");
END;
Texts.WriteLn( w );
Texts.Append( Oberon.Log, w.buf);
END RXAErrorHandler;
PROCEDURE RXErrorHandler( text : ARRAY OF CHAR );
BEGIN
CASE errorvar OF
strtoolong, linetoolong : Texts.WriteString( w, text ); Texts.WriteString( w," too long "); |
ELSE
Texts.WriteString( w, text );
END;
Texts.WriteLn( w );
Texts.Append( Oberon.Log, w.buf);
errorvar := noerror;
END RXErrorHandler;
PROCEDURE ParseTexts( text : Texts.Text; name : ARRAY OF CHAR; dfa : RXA.DFA; opti : BOOLEAN );
VAR
ch : CHAR;
r : Texts.Reader;
line, linec : ARRAY(nofline+1) OF CHAR;
lineind, i, beg, end : INTEGER;
wtext: Texts.Text;
x, y: INTEGER;
v: Viewers.Viewer;
linefull : BOOLEAN;
PROCEDURE Append( chr : CHAR );
BEGIN
IF lineind < LEN( line ) THEN line[lineind] := chr; INC(lineind) ELSE linefull := TRUE END;
END Append;
BEGIN
Oberon.AllocateUserViewer( Oberon.Mouse.X, x, y );
wtext := TextFrames.Text("");
v := MenuViewers.New(TextFrames.NewMenu("RX.Grep", "System.Close System.Copy System.Grow"),
TextFrames.NewText(wtext, 0), TextFrames.menuH, x, y);
Texts.OpenReader( r, text, 0 );
WHILE ( ~ r.eot ) DO
lineind := 0; linefull := FALSE;
REPEAT
Texts.Read( r, ch ); Append( ch );
UNTIL r.eot OR ( ch = CHR(cr) );
Append( CHR(0) );
IF linefull THEN
RXErrorHandler( " ERROR : line is too long ");
ELSE
beg := 0;
IF casesens THEN
RXA.Search( dfa, line, beg, end );
ELSE
COPY( line, linec ); i := 0; ch := linec[0];
WHILE ch # 0X DO linec[i] := MyCAP( ch ); INC(i); ch := linec[i] END;
RXA.Search( dfa, linec, beg, end );
END;
IF ( ( end >= 0 ) & (~opti) ) OR ( ( end < 0 ) & opti ) THEN
i := 0; WHILE i < lineind-1 DO Texts.Write(w, line[i] ); INC(i) END;
Texts.Append( wtext, w.buf );
END;
END;
END;
END ParseTexts;
PROCEDURE Grep*;
VAR
opti : BOOLEAN;
rx : ARRAY(nofline+1) OF CHAR;
error, erpos : INTEGER;
dfa : RXA.DFA;
s : Texts.Scanner;
text : Texts.Text;
name : ARRAY 32 OF CHAR;
BEGIN
Oberon.Collect(0);
Texts.OpenScanner( s, Oberon.Par.text, Oberon.Par.pos );
GetText( text, name, s );
GetOption( s, opti );
GetStr( s, rx );
IF errorvar = noerror THEN
RXA.New( rx, dfa, error, erpos );
IF (error = RXA.noerror) & ( text # NIL ) THEN
ParseTexts( text, name, dfa, opti )
ELSE
RXAErrorHandler( error, erpos )
END;
ELSE
RXErrorHandler("regular expression");
END;
END Grep;
PROCEDURE SetSearch*;
VAR
opti : BOOLEAN;
rx : ARRAY(nofline+1) OF CHAR;
ind : INTEGER;
error, erpos : INTEGER;
r : Texts.Reader;
BEGIN
Oberon.Collect(0);
Texts.OpenReader( r, Oberon.Par.text, Oberon.Par.pos );
GetOption( r, opti );
GetStr( r, rx );
IF errorvar = noerror THEN
RXA.New( rx, sdfa, error, erpos );
IF error # RXA.noerror THEN RXAErrorHandler( error, erpos ) END;
ELSE
RXErrorHandler("regular expression");
END;
(* RXA.Dump( sdfa, w ); Texts.Append( Oberon.Log, w.buf ); *)
END SetSearch;
PROCEDURE SetReplace*;
VAR r : Texts.Reader;
BEGIN
replset := TRUE;
Texts.OpenReader( r, Oberon.Par.text, Oberon.Par.pos );
Texts.Read(r, ch); (* << mmb *)
GetStr( r, replstr );
IF errorvar # noerror THEN RXErrorHandler("replace pattern"); END;
END SetReplace;
PROCEDURE SearchPattern( text : Texts.Text; textpos : LONGINT );
VAR
r : Texts.Reader;
beg, end, lineind : INTEGER;
ch : CHAR;
line : ARRAY(nofline+1) OF CHAR;
linelen : LONGINT;
linefull : BOOLEAN;
PROCEDURE Append( chr : CHAR );
BEGIN
IF lineind < LEN( line ) THEN
IF ~casesens THEN line[lineind] := MyCAP( chr ) ELSE line[lineind] := chr END;
INC(lineind);
ELSE
linefull := TRUE;
END;
END Append;
BEGIN
end := -1;
Texts.OpenReader( r, text, textpos );
WHILE ( ~ r.eot ) & ( end < 0 ) DO
lineind := 0; linefull := FALSE;
textpos := Texts.Pos( r );
REPEAT
Texts.Read( r, ch );
Append( ch );
UNTIL r.eot OR ( ch = CHR(cr) );
linelen := lineind;
Append( CHR(0) );
IF linefull THEN
RXErrorHandler( " ERROR : line is too long ");
ELSE
beg := 0;
RXA.Search( sdfa, line, beg, end );
END;
END;
IF end >= 0 THEN
stext := text; stextpos := textpos; slinelen := linelen; sbeg := beg; send := end; sreplaced := FALSE; COPY( line, sline );
END;
END SearchPattern;
PROCEDURE Search*;
VAR
frame : TextFrames.Frame;
textpos : LONGINT;
BEGIN
errorvar := noerror;
frame := Focus();
IF frame # NIL THEN
IF frame.hasCar THEN textpos := frame.carloc.pos ELSE textpos := 0 END;
SearchPattern( frame.text, textpos );
IF ( ~sreplaced ) & ( frame.text = stext ) THEN
Oberon.RemoveMarks( frame.X, frame.Y, frame.W, frame.H );
TextFrames.RemoveSelection( frame );
TextFrames.RemoveCaret( frame );
IF stextpos + send > TextFrames.Pos( frame, frame.X + frame.W, frame.Y ) THEN
TextFrames.Show( frame, stextpos + send-200 );
END;
TextFrames.SetSelection( frame, stextpos + sbeg, stextpos + send );
TextFrames.SetCaret( frame, stextpos + send );
END
END;
END Search;
PROCEDURE Replace*;
VAR
error, pos, i : INTEGER;
frame : TextFrames.Frame;
textpos : LONGINT;
BEGIN
IF ( ~sreplaced ) & replset THEN
frame := Focus();
IF frame # NIL THEN
IF frame.hasCar & ( frame.carloc.pos = stextpos + send ) THEN
RXA.Replace( sdfa, sline, replstr, sbeg, send, error, pos );
sreplaced := error = RXA.noerror;
IF sreplaced THEN
Oberon.RemoveMarks( frame.X, frame.Y, frame.W, frame.H );
TextFrames.RemoveSelection( frame );
TextFrames.RemoveCaret( frame );
Texts.Delete( frame.text, stextpos, stextpos + slinelen );
i := 0; WHILE( i < LEN( sline ) ) & ( sline[i] # 0X ) DO Texts.Write( w, sline[i] ); INC(i) END;
Texts.Insert( frame.text, stextpos, w.buf );
textpos := stextpos + pos;
SearchPattern( frame.text, textpos );
IF ~sreplaced THEN
IF stextpos + send > TextFrames.Pos( frame, frame.X + frame.W, frame.Y ) THEN
TextFrames.Show( frame, stextpos + send-200 );
END;
TextFrames.SetSelection( frame, stextpos + sbeg, stextpos + send );
TextFrames.SetCaret( frame, stextpos + send );
ELSE
IF frame.org # textpos - 200 THEN TextFrames.Show( frame, textpos-200 ) END;
TextFrames.SetCaret( frame, textpos );
END;
ELSE
RXAErrorHandler( error, pos );
END;
END
END;
END;
END Replace;
PROCEDURE ReplaceAll*;
VAR
frame : TextFrames.Frame;
textpos : LONGINT;
error, pos, i : INTEGER;
BEGIN
errorvar := noerror;
frame := Focus();
IF ( frame # NIL ) & replset THEN
IF frame.hasCar THEN textpos := frame.carloc.pos ELSE textpos := 0 END;
Oberon.RemoveMarks( frame.X, frame.Y, frame.W, frame.H );
TextFrames.RemoveSelection( frame );
TextFrames.RemoveCaret( frame );
LOOP
SearchPattern( frame.text, textpos );
IF ~sreplaced THEN
RXA.Replace( sdfa, sline, replstr, sbeg, send, error, pos );
IF error = RXA.noerror THEN
sreplaced := TRUE;
Texts.Delete( frame.text, stextpos, stextpos + slinelen );
i := 0; WHILE( i < LEN( sline ) ) & ( sline[i] # 0X ) DO Texts.Write( w, sline[i] ); INC(i) END;
Texts.Insert( frame.text, stextpos, w.buf );
textpos := stextpos + pos;
ELSE
RXAErrorHandler( error, pos );
RETURN
END;
ELSE
EXIT;
END;
END
END;
END ReplaceAll;
BEGIN
Texts.OpenWriter( w );
errorvar := noerror;
replset := FALSE;
sreplaced := TRUE;
sdfa := NIL;
END RX.